package com.duqc.qiangdan;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName QiangdanService
 * @Description QiangdanService
 * @Author duqc
 * @Date 2022/2/7
 **/
@Slf4j
@Service
@RequiredArgsConstructor
public class QiangdanService {
    /**
     * 总库存
     */
    private long nKuCuen = 0;
    /**
     * 商品key名字
     */
    private final String shangpingKey = "computer_key";
    /**
     * 获取锁的超时时间 秒
     */
    private final int timeout = 30 * 1000;

    private final RedisConfigUtil redisUtil;

    public List<String> qiangdan() {
        //抢到商品的用户
        List<String> shopUsers = new ArrayList<>();

        List<String> users = new ArrayList<>();
        for (int i = 0; i < 100001; i++) {
            users.add("用户-" + i);
        }

        //初始化仓库
        nKuCuen = 1;

        users.parallelStream().forEach(b -> {
            String shopUser = qiang(b);
            if (StringUtils.isNotBlank(shopUser)) {
                shopUsers.add(shopUser);
            }
        });
        return shopUsers;
    }

    /**
     * 模拟抢单动作
     *
     * @param b
     * @return String
     */
    private String qiang(String b) {
        //用户开抢时间
        long startTime = System.currentTimeMillis();

        //未抢到的情况下，30秒内继续获取锁
        while ((startTime + timeout) >= System.currentTimeMillis()) {
            //商品是否剩余
            if (nKuCuen <= 0) {
                break;
            }
            if (redisUtil.setnx(shangpingKey, b)) {
                //用户b拿到锁
                log.info("用户{}拿到锁...", b);
                try {
                    if (nKuCuen <= 0) {
                        break;
                    }
                    //模拟生成订单耗时操作，方便查看
                    TimeUnit.SECONDS.sleep(1);

                    nKuCuen -= 1;
                    log.info("用户{}抢单成功跳出...所剩库存:{}", b, nKuCuen);

                    return b + "抢单成功，所剩库存: " + nKuCuen;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    log.info("用户{}释放锁..." + b);
                    redisUtil.delnx(shangpingKey, b);
                }
            } else {
                //用户b没拿到锁，在超时范围内继续请求锁，不需要处理
                log.info("用户{}等待获取锁...", b);
            }
        }
        return "";
    }
}
